#include "drawclient.h"
#include "./ui_drawclient.h"
#include "ui_connectdialog.h"

DrawClient::DrawClient(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::DrawClient)
{
    ui->setupUi(this);
    // 初始化画板
    drawArea = new TcpClient();
    // 设置画笔粗细
    setPenWidth();
    // 设置画板大小
    drawArea->resize(540, 490);
    // 将画板添加到 UI 文件定义好的布局中
    ui->drawAreaLayout->addWidget(drawArea);

    // 颜色菜单
    // 设置动作组
    QActionGroup *colorGroup = new QActionGroup(this);
    colorGroup->addAction(ui->actionblack);
    colorGroup->addAction(ui->actionblue);
    colorGroup->addAction(ui->actionbrown);
    colorGroup->addAction(ui->actiongreen);
    colorGroup->addAction(ui->actionorange);
    colorGroup->addAction(ui->actionpurple);
    colorGroup->addAction(ui->actionred);
    colorGroup->addAction(ui->actionyellow);
    // 设置动作组中的项目互斥，每次只能选择一项
    colorGroup->setExclusive(true);
    // 设置菜单图标和槽函数
    ui->actionblack->setIcon(QIcon(":/images/black.png"));
    connect(ui->actionblack, &QAction::triggered, this, &DrawClient::setPenColor);
    ui->actionblue->setIcon(QIcon(":/images/blue.png"));
    connect(ui->actionblue, &QAction::triggered, this, &DrawClient::setPenColor);
    ui->actionbrown->setIcon(QIcon(":/images/brown.png"));
    connect(ui->actionbrown, &QAction::triggered, this, &DrawClient::setPenColor);
    ui->actiongreen->setIcon(QIcon(":/images/green.png"));
    connect(ui->actiongreen, &QAction::triggered, this, &DrawClient::setPenColor);
    ui->actionorange->setIcon(QIcon(":/images/orange.png"));
    connect(ui->actionorange, &QAction::triggered, this, &DrawClient::setPenColor);
    ui->actionpurple->setIcon(QIcon(":/images/purple.png"));
    connect(ui->actionpurple, &QAction::triggered, this, &DrawClient::setPenColor);
    ui->actionred->setIcon(QIcon(":/images/red.png"));
    connect(ui->actionred, &QAction::triggered, this, &DrawClient::setPenColor);
    ui->actionyellow->setIcon(QIcon(":/images/yellow.png"));
    connect(ui->actionyellow, &QAction::triggered, this, &DrawClient::setPenColor);
    // 工具菜单
    // 设置动作组
    QActionGroup *toolGroup = new QActionGroup(this);
    toolGroup->addAction(ui->actionpen);
    toolGroup->addAction(ui->actioneraser);
    // 设置动作组互斥
    toolGroup->setExclusive(true);
    ui->actionpen->setIcon(QIcon(":/images/pencil.png"));
    connect(ui->actionpen, &QAction::triggered, this, &DrawClient::resetPen);
    connect(ui->actionpen, &QAction::triggered, drawArea, &TcpClient::setPencilCursor);
    ui->actioneraser->setIcon(QIcon(":/images/eraser.png"));
    connect(ui->actioneraser, &QAction::triggered, this, &DrawClient::resetEraser);
    connect(ui->actioneraser, &QAction::triggered, drawArea, &TcpClient::setEraserCursor);
    connect(ui->actionclear, &QAction::triggered, this, &DrawClient::clearScreenSlot);
    // 设置粗细的菜单
    // 设置动作组
    QActionGroup *widthGroup = new QActionGroup(this);
    widthGroup->addAction(ui->actionregular);
    widthGroup->addAction(ui->actionbold);
    widthGroup->addAction(ui->actionlight);
    // 设置动作组互斥
    widthGroup->setExclusive(true);
    // 连接信号和槽
    connect(ui->actionregular, &QAction::triggered, this, &DrawClient::setPenWidth);
    connect(ui->actionbold, &QAction::triggered, this, &DrawClient::setPenWidth);
    connect(ui->actionlight, &QAction::triggered, this, &DrawClient::setPenWidth);
    // 主菜单
    connect(ui->actionconnect, &QAction::triggered, this, &DrawClient::showConnectDialog);
    connect(ui->actionexit, &QAction::triggered, this, &QWidget::close);
    // 关于
    connect(ui->actionabout, &QAction::triggered, this, &DrawClient::aboutSlot);
    // 连接按钮的信号和槽
    connect(ui->sendButton, &QAbstractButton::clicked, this, &DrawClient::sendWordSlot);
    connect(ui->abandonBtn, &QAbstractButton::clicked, this, &DrawClient::giveUpSlot);
    // 连接画板类中的信号和槽
    connect(drawArea, &TcpClient::signalNewMsg, this, &DrawClient::newMsgSlot);
    connect(drawArea, &TcpClient::signalNewUser, this, &DrawClient::newUserSlot);
    connect(drawArea, &TcpClient::signalNewTime, this, &DrawClient::timeLeftSlot);
    connect(drawArea, &TcpClient::signalNewWord, this, &DrawClient::newWordSlot);
    connect(drawArea, &TcpClient::signalBeGuessed, this, &DrawClient::beGuessedSlot);
    connect(drawArea, &TcpClient::signalUserLeft, this, &DrawClient::userLeftSlot);
    connect(drawArea, &TcpClient::signalCancelPainter, this, &DrawClient::cancelPainterSlot);

    // 初始化连接设定
    connectSet = new QSettings("YulinWei", "DrawClient");
    connectSet->setValue("ip", "127.0.0.1");
    connectSet->setValue("port", "50112");
    // connectSet->setValue("name", "Alice");

    // 置灰弃权按钮
    ui->abandonBtn->setEnabled(false);
}

DrawClient::~DrawClient()
{
    delete ui;
}

void DrawClient::closeEvent(QCloseEvent *event)
{
    // 创建一个对话框
    QMessageBox exitBox;
    exitBox.setAttribute(Qt::WA_QuitOnClose, false);
    // 设定对话框标题
    exitBox.setWindowTitle("确认");
    // 对话框文本
    exitBox.setText("是否确定退出？");
    // 对话框中的图片
    exitBox.setIconPixmap(QPixmap(":/images/question.png"));
    // 对话框中的按钮
    QPushButton *yesBtn = exitBox.addButton("是", QMessageBox::YesRole);
    exitBox.addButton("否", QMessageBox::NoRole);
    // 显示对话框
    exitBox.exec();
    // 如果点击「是」，断开连接并接受关闭事件
    if(exitBox.clickedButton() == (QAbstractButton *)yesBtn)
    {
        if(drawArea->isConnected)
        {
            disconnectFromServer();
        }
        event->accept();
    }
    // 否则忽略关闭事件
    else
        event->ignore();
}

void DrawClient::keyPressEvent(QKeyEvent *event)
{
    if(event->key() == Qt::Key_Enter || event->key() == Qt::Key_Return)
    {
        sendWordSlot();
    }
    else
        event->accept();
}

void DrawClient::writeSettings()
{
    // 将连接对话框的信息写入到设置信息中
    connectSet->setValue("ip", dialog->ui->addressEdit->text());
    connectSet->setValue("port", dialog->ui->portEdit->text());
    connectSet->setValue("name", dialog->ui->usernameEdit->text());
}

void DrawClient::readSettings()
{
    // 从设置信息中读取信息并覆盖到连接对话框
    QString ip = connectSet->value("ip").toString();
    QString port = connectSet->value("port").toString();
    QString name = connectSet->value("name").toString();
    dialog->ui->addressEdit->setText(ip);
    dialog->ui->portEdit->setText(port);
    dialog->ui->usernameEdit->setText(name);
}

void DrawClient::setPenColor()
{
    // 如果正在使用橡皮擦，忽略该操作
    if(ui->actioneraser->isChecked())
        return;
    // 根据被点击的菜单项设定对应的颜色
    if(ui->actionred->isChecked()){
        drawArea->setPenColor(QColor(255, 2, 2));
    }else if(ui->actionorange->isChecked()){
        drawArea->setPenColor(QColor(147, 122, 6));
    }else if(ui->actionyellow->isChecked()){
        drawArea->setPenColor(QColor(250, 251, 126));
    }else if(ui->actiongreen->isChecked()){
        drawArea->setPenColor(QColor(21, 254, 3));
    }else if(ui->actionblue->isChecked()){
        drawArea->setPenColor(QColor(3, 38, 254));
    }else if(ui->actionpurple->isChecked()){
        drawArea->setPenColor(QColor(228, 3, 254));
    }else if(ui->actionbrown->isChecked()){
        drawArea->setPenColor(QColor(147, 122, 6));
    }else{
        drawArea->setPenColor(QColor(4, 4, 4));
    }
}

void DrawClient::setPenWidth()
{
    // 如果正在使用橡皮擦，忽略该操作
    if(ui->actioneraser->isChecked())
        return;
    // 根据点击的菜单项设定画笔粗细
    if(ui->actionbold->isChecked()){
        drawArea->setPenWidth(9);
    }else if(ui->actionlight->isChecked()){
        drawArea->setPenWidth(2);
    }else{
        drawArea->setPenWidth(5);
    }
}

void DrawClient::resetPen()
{
    drawArea->setPencilCursor();
    setPenColor();
    setPenWidth();
}

void DrawClient::resetEraser()
{
    drawArea->setPenColor(QColor(255, 255, 255));
    drawArea->setPenWidth(15);
}

void DrawClient::clearScreenSlot()
{
    drawArea->clearImage();
}

void DrawClient::showConnectDialog()
{
    if(drawArea->isConnected)
    {
        disconnectFromServer();
        ui->actionconnect->setText("连接服务器...");
        ui->messageBox->append("已断开连接");
        ui->usernameLabel->clear();
    }
    else
    {
        // 初始化连接对话框
        dialog = new ConnectDialog();
        connect(dialog, &QDialog::accepted, this, &DrawClient::connectToServer);
        readSettings();
        dialog->ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(true);
        dialog->ui->buttonBox->button(QDialogButtonBox::Ok)->setText("确定");
        dialog->exec();
    }
}

void DrawClient::connectToServer()
{
    // 如果信息没有填写完整，弹出警告
    if(dialog->ui->addressEdit->text() == "" || dialog->ui->portEdit->text() == "" || dialog->ui->usernameEdit->text() == "")
    {
        dialog->showWarning();
        // qDebug() << dialog->isHidden();
        // 弹出警告提示后，连接对话框会被隐藏，这里重新令它显示
        dialog->close();
        showConnectDialog();
        return;
    }
    // 连接到服务器
    if(!drawArea->isConnected)
    {
        drawArea->setServerInfo(dialog->ui->addressEdit->text(), dialog->ui->portEdit->text().toInt(), dialog->ui->usernameEdit->text());
        drawArea->connectToServer();
        dialog->show();
        dialog->ui->buttonBox->button(QDialogButtonBox::Ok)->setText("正在连接");
        dialog->ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(false);
        drawArea->isConnected = drawArea->clientSocket->waitForConnected(5000);
        if(drawArea->isConnected)
        {
            drawArea->sendMsg(1, dialog->ui->usernameEdit->text());
            // 保存连接信息到配置文件
            writeSettings();
            // qDebug() << "isConnected";
            // 关闭连接对话框
            dialog->close();
            // 释放键盘
            dialog->releaseKeyboard();
            ui->usernameLabel->setText(connectSet->value("name").toString());
            ui->actionconnect->setText("断开连接");
            ui->messageBox->append("连接服务器成功");  
        }
        else
        {
            QMessageBox::warning(dialog, "错误", "连接失败，请检查信息是否正确", QMessageBox::Ok);
            dialog->close();
            showConnectDialog();
        }
    }
}

void DrawClient::disconnectFromServer()
{
    drawArea->disconnectFromServer();
    ui->userList->clear();
    ui->timeLeftLabel->clear();
}

void DrawClient::newMsgSlot(const QString& message)
{
    ui->messageBox->append(message);
}

void DrawClient::newUserSlot(const QString& list)
{
    ui->userList->clear();
    QList<QString> tempList = list.split(';');
    // qDebug() << list;
    for(const auto & i : tempList)
    {
        if(i != "")
            ui->userList->addItem(i);
    }
}

void DrawClient::timeLeftSlot(const QString& time)
{
    // qDebug() << time;
    ui->timeLeftLabel->setText(time + " 秒");
    // 如果剩余时间用完，置灰弃权按钮
    if(drawArea->isCurrentPainter && time.toUInt() == 0)
        ui->abandonBtn->setEnabled(false);
}

void DrawClient::newWordSlot(const QString& word)
{
    // 设置画笔
    resetPen();
    // 界面显示词语
    ui->wordLabel->setText(word);
    // 激活弃权按钮
    ui->abandonBtn->setEnabled(true);
    // 禁用消息文本框
    ui->messageEdit->setEnabled(false);
    // 置灰发送按钮
    ui->sendButton->setEnabled(false);
}

void DrawClient::userLeftSlot(int descriptor, const QString& name)
{
    ui->messageBox->append(name + tr("离开了"));
    QListWidgetItem *currentItem = ui->userList->takeItem(descriptor);
    delete currentItem;
    // 如果玩家人数小于 2，结束游戏
    if(ui->userList->count() < 2 && drawArea->isGamePlaying)
    {
        drawArea->clearImage();
        ui->abandonBtn->setEnabled(false);
        ui->wordLabel->clear();
        ui->timeLeftLabel->clear();
        ui->messageBox->append("在线玩家人数小于 2，游戏结束");
        drawArea->isGamePlaying = false;
        // 激活消息文本框
        ui->messageEdit->setEnabled(true);
        // 激活发送按钮
        ui->sendButton->setEnabled(true);
    }
}

void DrawClient::beGuessedSlot(const QString& message)
{
    ui->messageBox->append(message);
}

void DrawClient::sendWordSlot()
{
    if(!ui->messageEdit->text().isEmpty())
    {
        // 向服务端发送用户名和消息内容
        drawArea->sendMsg(3, ui->usernameLabel->text(), ui->messageEdit->text());
        // 清空消息文本框
        ui->messageEdit->clear();
    }
}

void DrawClient::giveUpSlot()
{
    if(drawArea->getIsCurrentPainter())
        drawArea->sendMsg(8, ui->usernameLabel->text());
    cancelPainterSlot();
}

void DrawClient::cancelPainterSlot()
{
    // 清空词语
    ui->wordLabel->clear();
    // 置灰弃权按钮
    ui->abandonBtn->setEnabled(false);
    // 激活消息文本框
    ui->messageEdit->setEnabled(true);
    // 激活发送按钮
    ui->sendButton->setEnabled(true);
}

void DrawClient::aboutSlot()
{
    QMessageBox::information(this, "关于", "Developer：Yulin Wei\nPowered by Qt", QMessageBox::Ok);
}
